package org.dht.com.tra;

import java.util.Map;

import org.dht.com.Observer;
import org.dht.com.msg.BigMessage;
import org.dht.com.msg.Message;

/**
 * The {@code CommunicationManager} interface is used to send messages
 * regardless of the implementation of the way in which they are sent.
 */
public interface CommunicationManager {
	/**
	 * Creates and sends a message specifying its type, the type of the response
	 * and the data. Used <code>sendMessage(message)</code> to send message
	 * 
	 * @param message
	 *            The type of the message that will be sent.
	 * @param typeReturn
	 *            The type of the response
	 * @return An object <T> of the specified type.
	 */
	public <T> T sendMessageUnicast(Message message, Class<T> typeReturn);

	/**
	 * Creates and sends a message specifying its type, the type of the response
	 * and the data. Used <code>sendMessage(message)</code> to send message
	 * 
	 * @param message
	 *            The type of the message that will be sent.
	 * @param typeReturn
	 *            The type of the response
	 * @param paramNameResult
	 *            Param name of result
	 * @return An object <T> of the specified type.
	 */
	public <T> T sendMessageUnicast(Message message, Class<T> typeReturn,
			String paramNameResult);

	/**
	 * Sends a message specifying its type, the type of the response and the
	 * data. Used Communicator instance called unicastManager to send message
	 * 
	 * @param message
	 *            Messages to send
	 */
	public void sendMessageUnicast(Message message);

	/**
	 * Creates and sends a multicast message specifying its type, the type of
	 * the response and the data. Used
	 * <code>sendMessageMultiCast(message)</code> to send message
	 * 
	 * @param <T>
	 *            Type return
	 * @param message
	 *            Message
	 * @param typeReturn
	 *            Type return
	 * @return Response
	 */
	public <T> T sendMessageMultiCast(Message message, Class<T> typeReturn);

	/**
	 * Creates and sends a multicast message specifying its type, the type of
	 * the response and the data. Used
	 * <code>sendMessageMultiCast(message)</code> to send message
	 * 
	 * @param <T>
	 *            Type return
	 * @param message
	 *            Message
	 * @param typeReturn
	 *            Type return
	 * @param paramNameResult
	 *            Param name of result
	 * @return Response
	 */
	public <T> T sendMessageMultiCast(Message message, Class<T> typeReturn,
			String paramNameResult);

	/**
	 * Sends a multicast message specifying its type, the type of the response
	 * and the data. Used Communicator instance called multicastManager to send
	 * message
	 * 
	 * @param message
	 *            Messages to send
	 */
	public void sendMessageMultiCast(Message message);

	/**
	 * Send big message. Used ByteTransfer instance called byteTransferManager
	 * to send message
	 * 
	 * @param bigMessage
	 *            Message to send
	 */
	public void sendBigMessage(BigMessage bigMessage);

	/**
	 * Send request to reciever big message. Used BytesTransfer instance to send
	 * request
	 * 
	 * @param message
	 *            Request message
	 * @return Response
	 */
	public BigMessage recieverBigMessage(Message message);

	/**
	 * Stop all process
	 */
	public void stopAll();

	/**
	 * Adds observer to communication
	 * 
	 * @param observer
	 *            Observer to add
	 */
	public void addObserver(Observer<Message> observer);

	/**
	 * Remove observer to communication
	 * 
	 * @param observer
	 *            Observer to remove
	 */
	public void removeObserver(Observer<Message> observer);

	/**
	 * Remove observer by name
	 * 
	 * @param name
	 *            Observer name
	 */
	public void removeObserver(String name);

	/**
	 * Initialize communication manager.
	 */
	public void init();

	/**
	 * Gets properties of communication
	 * 
	 * @return CommunicationProperties
	 */
	public Map<String, String> getCommunicationProperties();

	/**
	 * Sets properties for communication
	 * 
	 * @param communicationProperties
	 *            Properties
	 */
	public void setCommunicationProperties(
			Map<String, String> communicationProperties);
}
